home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / PriorityQueue / PriorityQueue.m < prev    next >
Text File  |  1995-06-12  |  10KB  |  543 lines

  1. /* NAME:
  2. **    PriorityQueue:Object
  3. **
  4. **    COPYRIGHT 1992 BY ONYSCHUK AND ASSOCIATES
  5. **    ALL RIGHTS RESERVED.
  6. **
  7. ** REVISION HISTORY:
  8. **    Sun Aug 16 14:14:03 EDT 1992    Mark Onyschuk
  9. **                    Starting point.
  10. **
  11. ** DESCRIPTION:
  12. **    A priority queue which dequeues objects sorted by
  13. **    unsigned integer priorities.
  14. **
  15. **    NOTE: priority(0) > priority(1) > priority(2) > ... 
  16. **
  17. ** DISCLAIMER:
  18. **    This is free software; you can redistribute it and/or modify
  19. **    it under the terms of the GNU General Public License as
  20. **    published by the Free Software Foundation; either version
  21. **    1, or (at your option) any later version.
  22. **
  23. **    This program is distributed in the hope that it will be
  24. **    useful, but WITHOUT ANY WARRANTY; without even the implied
  25. **    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  26. **    PURPOSE.  See the GNU General Public License for more
  27. **    details.
  28. **
  29. **    You should have received a copy of the GNU General Public
  30. **    License along with this program; if not, write to the Free
  31. **    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
  32. **    02139, USA.
  33. */
  34.  
  35. #import "PriorityQueue.h"
  36.  
  37.  
  38. /* DEFINITIONS **********************************************************/
  39.  
  40. #define DEFAULTSIZE    8
  41.  
  42.  
  43. /* MACROS ***************************************************************/
  44.  
  45. #define OBJECTAT(z)    (heap[z].object)
  46. #define PRIORITYOF(z)    (heap[z].priority)
  47.  
  48. #define HEAPMALLOC(q)    \
  49.     ((NODE*)NXZoneMalloc([self zone],sizeof(NODE)*(q)))
  50. #define HEAPREALLOC(q)    \
  51.     ((NODE*)NXZoneRealloc([self zone],heap,sizeof(NODE)*(q)))
  52. #define HEAPFREE()    \
  53.     (NXZoneFree([self zone],heap))
  54.  
  55.  
  56. @implementation PriorityQueue
  57.  
  58. /* INITIALIZING A PRIORITY QUEUE ****************************************/
  59.  
  60. - init
  61. {
  62.     return [self initCount:DEFAULTSIZE];
  63. }
  64.  
  65. - initCount:(int)count
  66. {
  67.     if ((self = [super init]) != nil)
  68.     {
  69.     top  = 0;
  70.         size = (count < 1) ? 1 : count;
  71.     heap = HEAPMALLOC(size + 1);
  72.     }
  73.     return self;
  74. }
  75.  
  76.  
  77. /* FREEING A PRIORITY QUEUE *********************************************/
  78.  
  79. - free
  80. {
  81.     HEAPFREE();
  82.     return [super free];
  83. }
  84.  
  85. - copyFromZone:(NXZone *)zone
  86. {
  87.     int i;
  88.     PriorityQueue *copy;
  89.     
  90.     copy = [[PriorityQueue allocFromZone:zone] initCount:size];
  91.     
  92.     for (i = top; i > 0; i--)
  93.     {
  94.         ((NODE *)(copy->heap))[i].object   = heap[i].object;
  95.         ((NODE *)(copy->heap))[i].priority = heap[i].priority;
  96.     }
  97.     
  98.     copy->top  = top;
  99.     copy->size = size;
  100.     
  101.     return copy;
  102. }
  103.  
  104.  
  105. /* ADDING/REMOVING OBJECTS FROM A PRIORITY QUEUE ************************/
  106.  
  107. /* NAME:
  108. **    - addObject:withPriority;
  109. **
  110. ** ARGUMENTS:
  111. **    anObject        object to be queued
  112. **    priority        unsigned integer priority
  113. **
  114. ** LAST EDITED:
  115. **    Sun Aug 23 15:17:03 EDT 1992    Mark Onyschuk
  116. **
  117. ** DESCRIPTION:
  118. **    Adds an object to the priority queue.
  119. **
  120. ** ALGORITHM:
  121. **    begin
  122. **        top <- top + 1
  123. **
  124. **        if top > size(heap)
  125. **        begin
  126. **        size(heap) = size(heap * 2)
  127. **        end
  128. **
  129. **        heap[top].object <- anObject
  130. **        heap[top].priority <- priority
  131. **
  132. **        i = top;
  133. **        j = parentOf(i);
  134. **
  135. **        while (i <> 1) && (priorityOf(i) < priorityOf(j))
  136. **        begin
  137. **        swap objects and priorities of i and j
  138. **
  139. **        i <- j;
  140. **        j <- parentOf(i);
  141. **        end
  142. **    end
  143. **
  144. ** RETURNS:
  145. **    self;
  146. */
  147.  
  148. - addObject:anObject withPriority:(unsigned int)priority
  149. {
  150.     int        i,
  151.             j;
  152.     NODE     temp;    
  153.  
  154.  
  155.     top += 1;
  156.         
  157.     if (top > size)
  158.     {
  159.         size *= 2;
  160.     heap  = HEAPREALLOC(size + 1);
  161.     }    
  162.  
  163.     
  164.     OBJECTAT(top) = anObject;
  165.     PRIORITYOF(top) = priority;
  166.     
  167.     for (i=top, j=i/2; (i>1) && (PRIORITYOF(i) < PRIORITYOF(j)); i=j, j=i/2)
  168.     { 
  169.     temp.object = OBJECTAT(i);
  170.     temp.priority = PRIORITYOF(i);
  171.     
  172.     OBJECTAT(i) = OBJECTAT(j);
  173.     PRIORITYOF(i) = PRIORITYOF(j);
  174.     
  175.     OBJECTAT(j) = temp.object;
  176.     PRIORITYOF(j) = temp.priority;
  177.     }
  178.     
  179.     return self;    
  180. }
  181.  
  182. /* NAME:
  183. **    - removeObject;
  184. **
  185. ** ARGUMENTS:
  186. **    none
  187. **
  188. ** LAST EDITED:
  189. **    Sun Aug 23 15:17:03 EDT 1992    Mark Onyschuk
  190. **
  191. ** DESCRIPTION:
  192. **    Removes an object from the priority queue.
  193. **
  194. ** ALGORITHM:
  195. **    begin
  196. **        if (isEmpty(heap))
  197. **        return nil
  198. **
  199. **        anObject <- objectAt(1)
  200. **
  201. **        move the top object and priority to the beginning (1)
  202. **        top <- top - 1
  203. **        i <- 1
  204. **
  205. **        while (i <= top / 2)
  206. **        begin
  207. **        j = objectOfMaxPriority(i*2, i*2 + 1)
  208. **
  209. **        if (priorityOf(i) > priorityOf(j))
  210. **        begin
  211. **            swap objects and priorities of i and j
  212. **            i <- j
  213. **        end else begin
  214. **            return anObject
  215. **        end
  216. **        end
  217. **        return anObject
  218. **    end
  219. **
  220. ** RETURNS:
  221. **    object from the queue with top priority, or
  222. **    nil if the queue is empty.
  223. */
  224.  
  225. - removeObject;
  226. {
  227.     int        i,
  228.             j;
  229.  
  230.     NODE    temp;
  231.     
  232.     id        anObject;
  233.     
  234.         
  235.  
  236.     if (top == 0)
  237.         return nil;
  238.  
  239.     anObject  = OBJECTAT(1);
  240.     
  241.          
  242.     OBJECTAT(1) = OBJECTAT(top);
  243.     PRIORITYOF(1) = PRIORITYOF(top);
  244.     
  245.     
  246.     i    = 1;
  247.     top -= 1;
  248.  
  249.     while (i <= top/2)
  250.     {
  251.         if ((PRIORITYOF(i*2) < PRIORITYOF((i*2) + 1)) || ((i*2) == top))
  252.         j =  i*2;
  253.     else
  254.         j = (i*2) + 1;
  255.     
  256.         if (PRIORITYOF(i) > PRIORITYOF(j))
  257.     {
  258.         temp.object = OBJECTAT(i);
  259.         temp.priority = PRIORITYOF(i);
  260.         
  261.         OBJECTAT(i) = OBJECTAT(j);
  262.         PRIORITYOF(i) = PRIORITYOF(j);
  263.         
  264.         OBJECTAT(j) = temp.object;
  265.         PRIORITYOF(j) = temp.priority;
  266.         
  267.         i = j;
  268.     }
  269.     else
  270.     {
  271.         return anObject;
  272.     }
  273.     }
  274.     return anObject;
  275. }    
  276.     
  277.  
  278. /* DETERMINING THE HIGHEST PRIORITY IN A PRIORITY QUEUE *****************/
  279.  
  280. /* NAME:
  281. **    - (unsigned)highestPriority
  282. **
  283. ** ARGUMENTS:
  284. **    none.
  285. **
  286. ** DESCRIPTION:
  287. **    Returns the highest priority occurring in the priority
  288. **    queue.
  289. **
  290. ** RETURNS:
  291. **    the highest priority occurring in the queue, or
  292. **    the latest priority occurring in the queue if the queue is empty.
  293. */
  294.  
  295. - (unsigned)highestPriority
  296. {
  297.     return PRIORITYOF(1);
  298. }
  299.  
  300.     
  301. /* COUNTING THE NUMBER OF OBJECTS IN A PRIORITY QUEUE *******************/
  302.  
  303. /* NAME:
  304. **    -(int)count;
  305. **
  306. ** ARGUMENTS:
  307. **    none.
  308. **
  309. ** LAST EDITED:
  310. **    Sun Aug 23 15:17:03 EDT 1992    Mark Onyschuk
  311. **
  312. ** DESCRIPTION:
  313. **    Returns the number of objects currently queued.
  314. **
  315. ** RETURNS:
  316. **    count of objects currently in the queue.
  317. */
  318.  
  319. - (unsigned int)count
  320. {
  321.     return top;
  322. }
  323.  
  324.  
  325. /* COMPARING AND COMBINING PRIORITY QUEUES ******************************/
  326.  
  327. /* NAME:
  328. **    - (BOOL)isEqual:anObject
  329. **
  330. ** ARGUMENTS:
  331. **    anObject        a PriorityQueue
  332. **
  333. ** LAST MODIFIED:
  334. **    Sun Aug 23 15:17:03 EDT 1992    Mark Onyschuk
  335. **
  336. ** DESCRIPTION:
  337. **    Compares <anObject> with the reciever and returns YES if
  338. **    <anObject> is a PriorityQueue, and both <anObject> and self
  339. **    contain the same objects in the same order.
  340. **
  341. ** RETURNS:
  342. **    YES if <anObject> is equal to the receiver, or
  343. **    NO otherwise.
  344. */
  345.  
  346. - (BOOL)isEqual:anObject
  347. {
  348.     int i;
  349.     
  350.     if (anObject == self)
  351.         return YES;
  352.     
  353.     if (([anObject isKindOf:[self class]]) &&
  354.         ((i = [anObject count]) == [self count]))
  355.     {
  356.         /* we make copies because priority queues are partially
  357.     ** ordered trees and the contents of one queue and another
  358.     ** though equal might be arranged different order inside the
  359.     ** tree.
  360.     */
  361.     id copyA = [self copy];
  362.     id copyB = [anObject copy];
  363.  
  364.     while ((i--) && ([copyA removeObject] == [copyB removeObject]))
  365.         ;
  366.  
  367.     return (i < 0) ? YES : NO;
  368.     }
  369.     return NO;
  370. }
  371.  
  372.  
  373. /* NAME:
  374. **    - appendQueue:(PriorityQueue *)otherQueue
  375. **
  376. ** ARGUMENTS:
  377. **    otherQueue        source queue
  378. **
  379. ** LAST MODIFIED:
  380. **    Sun Aug 23 15:17:03 EDT 1992    Mark Onyschuk
  381. **
  382. ** DESCRIPTION:
  383. **    Appends the contents of <otherQueue> to the reciever.
  384. **
  385. ** RETURNS:
  386. **    self.
  387. */
  388.  
  389. - appendQueue:(PriorityQueue *)otherQueue
  390. {
  391.     int i;
  392.  
  393.     for (i = otherQueue->top; i > 0; i--)
  394.         [self addObject : ((NODE *)(otherQueue->heap))[i].object
  395.        withPriority : ((NODE *)(otherQueue->heap))[i].priority];
  396.  
  397.     return self;
  398. }
  399.  
  400.  
  401. /* GETTING AND SETTING THE CAPACITY OF A PRIORITY QUEUE *****************/
  402.  
  403. /* NAME:
  404. **    -(unsigned int)capacity
  405. **
  406. ** ARGUMENTS:
  407. **    none.
  408. **
  409. ** LAST EDITED:
  410. **    Sun Aug 23 15:17:03 EDT 1992    Mark Onyschuk
  411. **
  412. ** DESCRIPTION:
  413. **    Returns the maximum number of objects that can be stored in the
  414. **    Queue without allocating more memory for it. When new memory is
  415. **    allocated, it's taken from the same zone that was specified
  416. **    when the Queue was created.
  417. **
  418. ** RETURNS:
  419. **    capacity.
  420. */
  421.  
  422. - (unsigned int)capacity
  423. {
  424.     return size;
  425. }
  426.  
  427. /* NAME:
  428. **    - setAvailableCapacity:(unsigned int)capacity
  429. **
  430. ** ARGUMENTS:
  431. **    capacity            unsigned integer
  432. **
  433. ** LAST MODIFIED:
  434. **    Tue Sep  1 15:56:18 EDT 1992    Mark Onyschuk
  435. **
  436. ** DESCRIPTION:
  437. **    Allocates or reallocates heap memory to contain
  438. **    <capacity> objects.
  439. **
  440. ** RETURNS:
  441. **    nil if <capacity> is less than <top>, or
  442. **    self otherwise.
  443. */
  444.  
  445. - setAvailableCapacity:(unsigned int)capacity
  446. {
  447.     if (capacity < top)
  448.         return nil;
  449.  
  450.     size  = capacity;
  451.     heap  = HEAPREALLOC(size + 1);
  452.     
  453.     return self;
  454. }
  455.  
  456.  
  457. /* EMPTYING A PRIORITY QUEUE ********************************************/
  458.  
  459. - empty
  460. {
  461.     top = 0;
  462.     return self;
  463. }
  464.  
  465. - freeObjects
  466. {
  467.     for (; top > 0; top--)
  468.         [OBJECTAT(top) free];
  469.  
  470.     return self;
  471. }   
  472.  
  473.  
  474. /* SENDING MESSAGES TO OBJECTS ******************************************/
  475.  
  476. - makeObjectsPerform:(SEL)aSelector
  477. {
  478.     int    i;
  479.     
  480.     for (i = top; i > 0; i--)
  481.         if ([OBJECTAT(i) respondsTo:aSelector])
  482.         [OBJECTAT(i) perform:aSelector];
  483.     
  484.     return self;
  485. }
  486.  
  487. - makeObjectsPerform:(SEL)aSelector with:anObject
  488. {
  489.     int    i;
  490.     
  491.     for (i = top; i > 0; i--)
  492.         if ([OBJECTAT(i) respondsTo:aSelector])
  493.         [OBJECTAT(i) perform:aSelector with:anObject];
  494.  
  495.     return self;
  496. }
  497.  
  498.  
  499. /* READING AND WRITING TYPED STREAMS ************************************/
  500.  
  501. - read:(NXTypedStream *)stream
  502. {
  503.     int i;
  504.     
  505.     [super read:stream];
  506.     
  507.     NXReadType(stream, "i", &size);
  508.     NXReadType(stream, "i", &top);
  509.  
  510.     if (heap)
  511.         free(heap);
  512.  
  513.     heap = (NODE *)HEAPMALLOC(size+1);
  514.     
  515.     for (i = 1; i <= top; i ++)
  516.     {
  517.     OBJECTAT(i) = NXReadObject(stream);
  518.         NXReadType(stream, "i", &(PRIORITYOF(i)));
  519.     }
  520.     
  521.     return self;
  522. }
  523.  
  524. - write:(NXTypedStream *)stream
  525. {
  526.     int i;
  527.     
  528.     [super write:stream];
  529.     
  530.     NXWriteType(stream, "i", &size);
  531.     NXWriteType(stream, "i", &top);
  532.  
  533.     for (i = 1; i < top; i ++)
  534.     {
  535.         NXWriteObject(stream, OBJECTAT(i));
  536.     NXWriteType(stream, "i", &(PRIORITYOF(i))); 
  537.     }
  538.     
  539.     return self;
  540. }
  541.  
  542. @end
  543.